using System;
using System.Buffers;
using System.Numerics;
using Beefly.Json.Exceptions;
using Beefly.Json.Meta;

namespace Beefly.Json.Extensions;

static class BufferWriterExtension
{
    private const int SIZE = 1024;
    
    public static void WriteBooleanChar(this IBufferWriter<char> writer, ref bool value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref sbyte value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref byte value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref short value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref ushort value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref int value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref uint value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref long value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref ulong value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref Int128 value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref UInt128 value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref BigInteger value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref float value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }
    
    public static void WriteNumberChar(this IBufferWriter<char> writer, ref double value)
    {
        var span = writer.GetSpan(SIZE);
        if (!value.TryFormat(span, out var written))
        {
            throw new NumberFormatWriterException();
        }
        writer.Advance(written);
    }

    public static void WriteChar(this IBufferWriter<char> writer, char value)
    {
        var span = writer.GetSpan(1);
        span[0] = value;
        writer.Advance(1);
    }

    public static void WriteObjectBeginChar(this IBufferWriter<char> writer)
    {
        writer.WriteChar(JsonSymbol.BRACKET_B_L);
    }
    
    public static void WriteObjectEndChar(this IBufferWriter<char> writer)
    {
        writer.WriteChar(JsonSymbol.BRACKET_B_R);
    }

    public static void WriteArrayBeginChar(this IBufferWriter<char> writer)
    {
        writer.WriteChar(JsonSymbol.BRACKET_C_L);
    }
    
    public static void WriteArrayEndChar(this IBufferWriter<char> writer)
    {
        writer.WriteChar(JsonSymbol.BRACKET_C_R);
    }

    public static void WriteCommaChar(this IBufferWriter<char> writer)
    {
        writer.WriteChar(JsonSymbol.COMMA);
    }
}